<?php
/**
 * Created by PhpStorm.
 * User: Admin
 * Date: 2020-08-01
 * Time: 下午 08:57
 */
namespace Lib;

/**
 * Class Functions
 * @package Lib
 * 
 * @property-read \Lib\Server $server
 */
class Functions extends Injector {
    const PATH_COMPARE_CHILD = 2;
    const PATH_COMPARE_PARENT = -2;
    const PATH_COMPARE_SAME = 1;
    const PATH_COMPARE_DIFF = 0;

    /**
     * 格式化路径
     * @param $path
     * @param string $ps
     * @return mixed
     */
    public function formatPath($path, $ps='/') {
        return str_replace('/', $ps, 
            preg_replace('#/+#', '/', 
                str_replace(['\\', '/'], '/', $path)
            )
        );
    }

    /**
     * 将路径转为标准路径
     * @param $path
     * @return string
     */
    public function absolutePath($path) {
        $path = $this->formatPath($path);
        $pathSeg = array_map('trim', explode('/', $path));
        
        for($i=0; $i<count($pathSeg); $i++) {
            if($pathSeg[$i] == '.') {
                array_splice($pathSeg, $i, 1);
                $i--;
            } else if($pathSeg[$i] == '..') {
                if($i > 0) {
                    array_splice($pathSeg, $i-1, 2);
                    $i -= 2;
                } else{
                    array_splice($pathSeg, $i, 1);
                    $i--;
                }
            }
        }
        
        return rtrim(implode('/', $pathSeg), '/');
    }

    /**
     * 路径比较
     * @param $parent
     * @param $child
     * @param bool $ignoreCase
     * @return int
     */
    public function pathCompare($parent, $child, $ignoreCase=false) {
        $parent = $this->absolutePath($parent);
        $child = $this->absolutePath($child);
        
        $parent .= '/';
        $child .= '/';
        
        if($ignoreCase) {
            $parent = strtolower($parent);
            $child = strtolower($child);
        }
        
        $parentLength = strlen($parent);
        $childLength = strlen($child);
        
        if(substr($child, 0, $parentLength) == $parent) {
            if($parentLength < $childLength) {
                return self::PATH_COMPARE_CHILD;
            } else if($parentLength == $childLength) {
                return self::PATH_COMPARE_SAME;
            }
        }
        
        if(substr($parent, 0, $childLength) == $child && $childLength < $parentLength) {
            return self::PATH_COMPARE_PARENT;
        }
        
        return self::PATH_COMPARE_DIFF;
    }

    /**
     * 相对路径
     * @param $source
     * @param $target
     * @return string
     */
    public function calcRelativePath($source, $target) {
        $source = $this->absolutePath($source);
        $target = $this->absolutePath($target);
        
        $sourceSeg = explode('/', $source);
        $targetSeg = explode('/', $target);
        
        foreach($sourceSeg as $i => $row) {
            if($sourceSeg[$i] != $targetSeg[$i]) {
                return str_repeat('../', count(array_slice($sourceSeg, $i))) 
                    . implode('/', array_slice($targetSeg, $i));
            }
        }
        
        $count = count($sourceSeg);
        $tarCount = count($targetSeg);
        
        if($count == $tarCount) {
            return './';
        }
        
        return implode('/', array_slice($targetSeg, $count));
    }

    /**
     * 获取$_SERVER变量对象
     * @return Server
     */
    public function server() {
        return $this->server;
    }

    /**
     * 重定向
     * @param $url
     * @param array $params
     */
    public function redirectTo($url, $params=[]) {
        $url .= empty($params) ? '' : ('/?' . http_build_query($params));
        header("location: $url");
        exit;
    }

    /**
     * @param $params
     * @param bool $clean
     * @return mixed|string
     */
    public function buildCurrentUrl($params, $clean=false) {
        $get = $_GET;

        if($clean) {
            $get = [];
        }

        foreach ($params as $key => $row) {
            if($row === null) {
                unset($get[$key]);
            } else {
                $get[$key] = $row;
            }
        }

        $path = $this->server->requestPath();
        $path .= empty($get) ? '' : '?' . http_build_query($get);
        return $path;
    }

    /**
     * 生成唯一id
     * @param int $length
     * @return string
     */
    public function uniqid($length = 16) {
        static $ID = 0;
        return substr(md5(($ID++) . $_SERVER['REMOTE_ADDR'] . session_id() . uniqid('', true)), floor((32-$length)/2), $length);
    }
    
    public function extname($path) {
        $dot = strrpos($path, '.');
        
        if($dot !== false) {
            return substr($path, $dot+1);
        }
        
        return '';
    }
    
    public function filename($path) {
        $basename = basename($path);
        $dot = strrpos($basename, '.');
        
        if($dot !== false) {
            return substr($basename, 0, $dot);
        }

        return $basename;
    }
    
    public function newUrlCreator($url=null) {
        return new UrlCreator($url);
    }
}

// $FH = new FunctionalHelper;

